In computing, virtualization hides the physical characteristics of a computing platform from the users. A user sees an abstract, emulated, computing platform and is unaware that applications are not running directly on the underlying hardware.
In a virtualized system a virtual machine creates “a simulated computer environment” for its guest software. The guest software may include user applications and complete operating systems. The guest software executes as if it were running directly on the underlying physical hardware and is, otherwise, unaware that it is operating in a virtualized environment. To provide isolation between virtual machines and between virtual machines and host software, most virtualized systems control access to physical system resources. Guests may also be restricted from accessing specific peripheral devices, or may be limited to a subset of the device's native capabilities, depending on the hardware access policy implemented by the virtualization host. Similarly, guests may be confined to a subset of the host's memory. This separation or control has allowed virtualization to run multiple independent “machines” on a single hardware platform, assuring security and minimizing, actually eliminating, interference between virtual machines.
Often, in implementing virtualized systems, binary translation is applied. Binary translation is the translation of instructions or code in one instruction set or language, i.e., a “source,” into another through translation of the code. Sequences of instructions are translated from the source to the target instruction set.
“Full virtualization” provides a virtual machine environment that is a complete simulation of the underlying hardware. Software, e.g., almost any operating system, that is otherwise capable of running on the hardware is run in the virtual machine. The concept of full virtualization is well known to those of ordinary skill in the art.
Some virtualization products from VMware Inc., Palo Alto, Calif., employ binary translation to modify x86 software “on the fly.” Instructions, i.e., input language (IL), that may contain privileged instructions that could affect the host, as a whole, or other virtual machines, are replaced with a safe sequence of instructions, i.e., output language (OL). It should be noted that IL and OL may be the same in some instances, e.g., x86 instructions.
As known to those of ordinary skill in the art, there are privileged instructions that are kept for Operating System or Kernel applications and are not meant to be used by user written programs. In a virtualized system, these privileged instructions often cannot be executed unmodified. Accordingly, the binary translator replaces the privileged instructions with an equivalent “safe” sequence of instructions that has the intended effect of the privileged instruction(s) on the virtual machine's state.
The binary translator is usually implemented as a software module running, for example, in a virtual machine monitor (VMM) or hypervisor. As is known, the binary translation of some instructions or some series of instructions requires nontrivial code transformation, possibly resulting in OL code that runs significantly slower than the unmodified IL code would have done. Further, the cost of the translation process itself also matters when using dynamic translation, but usually to a much lesser degree as code is generally translated once but executed many times.
The Intel Architecture Software Developer's Manual, Volume 3: System Programming, copyright 1999 by Intel Corporation, incorporated herein by reference for all purposes, describes that, in some computers, physical memory is organized into a plurality of memory segments. Referring now to FIG. 1, a memory space 100 is divided into a plurality of memory segments 102-1 . . . 102-n. Each memory segment 102 has a segment descriptor SEGDES associated with it that defines properties of that memory segment such as:
a) access_rights:                readable,        readable_and_writable, or        neither_readable_nor_writable        
b) limit_type: expand_up or grow_down
c) limit: depending on limit_type this is either:                expand_up: the highest valid address, or        grow_down: one less than the lowest valid address.        
d) limit_size: maximum number of bits in the limit (16 or 32).
As known, although not shown in FIG. 1, memory segments may overlap in a memory, be nested within each other or leave gaps resulting in some portion of memory being inaccessible through any segment.
A segment descriptor table 104 is provided that contains the segment descriptors SEGDES with a corresponding reference referred to as a segment selector, SEGSEL. The segment selector SEGSEL is not stored in the table but is used to index the table. Thus, the segment descriptor table 104 has a plurality of segment descriptor entries, 106-1 . . . 106-n, with a segment selector SEGSEL indexing a segment descriptor SEGDES.
Further, referring now to FIG. 2, a plurality of segment registers 202, 204, 206 are provided. As known, the number m of segment registers provided is much less than the number n of different segment selectors available for use, i.e., m<<n. These registers are shown in the form of a table for descriptive purposes only. As is generally known to one of ordinary skill in the art, a segment register 202, 204, 206 contains a cross-reference of a segment selector SEGSEL to a segment descriptor SEGDES. In general, a segment register is provided for a particular type of information in memory, for example, a segment register SR-1 may identify where data is stored in memory and another segment register SR-2 may identify where application code is stored.
An instruction may contain one or more memory references. Each memory reference, called a segment_access below, accesses the memory of a segment by specifying:                a segment register,        an address within the segment,        the number of bytes to be accessed, and        the type of requested access, i.e., read, write or read/write. (Where read/write represents a read followed by a write.)        
Prior to allowing an instruction to access the segment's memory, it must be determined whether or not the request is proper. Thus the request must meet the access rights and the address limits of the segment for the range of addresses attempted to be read from or written to, as defined by the corresponding segment descriptor. It is also noted that, with respect to the checking of memory segment access rights, write authorization always includes read authorization.
A segment check ensures that a requested segment_access is valid for a given segment descriptor SEGDES by determining if:
a) the type of access (read or write) is allowed, and
b) the range of bytes to be accessed [address, address+operand_size−1] is valid
As known, in order to be valid, a segment_access request has to satisfy certain conditions on the segment_descriptor referenced by the segment_register in the access request.
The conditions are evaluated, generally, according to the following:
a) read segment_register specified by the segment_access.segment_register to obtain the cached segment_descriptor information;
b) check that segment_access.access_type is allowed by the segment_descriptor.access_rights;
c) check that the address range can be accessed.
From the perspective of a binary translator, verifying the access to a segment's memory is complicated as hardware segmentation in OL cannot be used because OL, unlike IL, in most cases, almost certainly will not have segmentation. The OL language is deficient, therefore, compared with the IL language which most likely has segmentation. Because hardware cannot be used to do the segment checks and address conversion in OL, another mechanism must be provided.
Accordingly, it would be advantageous if a mechanism were provided for more efficient runtime translations of segmented memory access requests emitted by a binary translator.